package Netty.NIO;

import java.io.BufferedWriter;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author caihe
 * @date 2021/11/26 10:45
 */
public class SelectorNioServer_a {

    public static void main(String[] args) throws IOException {
        // 打开多路复用组件 即开启使用epoll
        Selector selector = Selector.open();

        // 创建nio
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 绑定端口
        serverSocketChannel.bind(new InetSocketAddress(9090));
        // 设置非阻塞
        serverSocketChannel.configureBlocking(false);

        // 将连接事件注册到 多路复用器 中
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            // 多路复用器获取当前准备好的通道
            int select = selector.select();
            if (select == 0) {
                continue;
            }
            // 获取准备好的所有事件对应的key
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            // 遍历处理所有的事件
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                if (key.isAcceptable()) {
                    // 处理连接事件  使得服务端接受新的连接
                    SocketChannel accept = serverSocketChannel.accept();
                    // 设置此连接为非阻塞
                    accept.configureBlocking(false);
                    // 将此连接的读取事件注册到selector多路复用器中
                    accept.register(selector, SelectionKey.OP_READ);
                }
                if (key.isReadable()) {
                    // 处理读取事件
                    // 通过key获取当前事件的通道
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    // 定义一个缓冲区
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    // 从通道中读到缓冲区
                    int read = socketChannel.read(readBuffer);
                    if (read > 0) {
                        System.out.println("收到数据：" + new String(readBuffer.array()).trim());
                    } else if (read == -1) {
                        socketChannel.close();
                    }
                    socketChannel.register(selector, SelectionKey.OP_WRITE);
                }
                if (key.isWritable()) {
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.wrap("返回给客户端的数据...".getBytes());
                    socketChannel.write(buffer);
                    System.out.println("key.isWritable()");
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }

            }


        }


    }

}
